package com.universalInterface.common.result;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.http.HttpStatus;

import java.io.Serializable;

/**
 * @author Lx
 * @date 2023/12/8 14:43
 * @description 统一封装响应结果
 */
@Data
@Schema(name = "ApiResult", description = "封装响应结果")
public class ApiResult<T> implements Serializable {

	private static final long serialVersionUID = -8678909792003478580L;

	@Schema(name = "code", description = "状态码", example = "200")
	private int code;

	@Schema(name = "message", description = "状态码描述", example = "成功")
	private String message;

	@Schema(name = "timestamp", description = "时间戳", requiredMode = Schema.RequiredMode.REQUIRED)
	private long timestamp;

	@Schema(name = "data", description = "响应数据")
	private T data;

	private ApiResult() {
		this.timestamp = System.currentTimeMillis();
	}

	private ApiResult(int code, String message) {
		this.code = code;
		this.message = message;
		this.timestamp = System.currentTimeMillis();
	}

	private ApiResult(int code, String message, T data) {
		this.code = code;
		this.message = message;
		this.data = data;
		this.timestamp = System.currentTimeMillis();
	}

	/**
	 * 返回枚举类ApiCode中的状态码和状态描述。
	 *
	 * @param apiCode 枚举类ApiCode
	 * @return
	 */
	public static ApiResult result(ApiCode apiCode) {
		return result(apiCode, null);
	}

	/**
	 * 返回枚举类ApiCode中的状态码和状态描述，以及响应数据data。
	 *
	 * @param apiCode 枚举类ApiCode
	 * @param data    响应数据
	 * @param <T>
	 * @return
	 */
	public static <T> ApiResult<T> result(ApiCode apiCode, T data) {
		return result(apiCode, null, data);
	}

	/**
	 * 返回枚举类ApiCode中的状态码，状态描述，以及响应数据data。
	 *
	 * @param apiCode 枚举类ApiCode
	 * @param message 状态码描述
	 * @param data    响应数据
	 * @param <T>
	 * @return
	 */
	public static <T> ApiResult<T> result(ApiCode apiCode, String message, T data) {
		if (isBlank(message)) {
			message = apiCode.getMessage();
		}
		return new ApiResult(apiCode.getCode(), message, data);
	}

	/**
	 * 1、可以配合HttpStatus类中的code = httpStatus.value(), message = httpStatus.getReasonPhrase()使用
	 * <p>
	 * 2、传入参数code和message的值，返回对应的响应结果
	 *
	 * @param code    状态码
	 * @param message 状态码描述
	 * @return
	 */
	public static ApiResult result(int code, String message) {
		return result(code, message, null);
	}

	/**
	 * 传入参数code、message和响应数据data的值，返回对应的响应结果
	 *
	 * @param code    状态码
	 * @param message 状态码描述
	 * @param data    响应数据
	 * @param <T>
	 * @return
	 */
	public static <T> ApiResult<T> result(int code, String message, T data) {
		return new ApiResult<T>(code, message, data);
	}


	/**
	 * 返回枚举类ApiCode中的状态码（200）和状态描述。
	 *
	 * @return 成功
	 */
	public static ApiResult success() {
		return result(ApiCode.OK);
	}

	/**
	 * 返回枚举类ApiCode中的状态码（200），传入的状态描述。
	 * <p>如果message和data的类型都是String，将会不好区分
	 *
	 * @param message 状态描述
	 * @return 成功
	 */
	public static ApiResult success(String message) {
		return result(ApiCode.OK, message, null);
	}

	/**
	 * 返回枚举类ApiCode中的状态码（200）和状态描述，以及响应数据data。
	 * <p>如果message和data的类型都是String，将会不好区分
	 *
	 * @param data 响应数据
	 * @param <T>
	 * @return 成功
	 */
	public static <T> ApiResult<T> success(T data) {
		return result(ApiCode.OK, null, data);
	}

	/**
	 * 返回枚举类ApiCode中状态码（200），传入的状态描述，以及响应数据data。
	 *
	 * @param message 状态描述
	 * @param data    响应数据
	 * @param <T>
	 * @return 成功
	 */
	public static <T> ApiResult<T> success(String message, T data) {
		return result(ApiCode.OK, message, data);
	}

	/**
	 * 返回枚举类ApiCode中状态码（500）和状态描述。
	 *
	 * @return 失败
	 */
	public static ApiResult error() {
		return result(ApiCode.INTERNAL_SERVER_ERROR);
	}

	/**
	 * 返回枚举类ApiCode中状态码（500），以及传入的状态描述。
	 *
	 * @param message
	 * @return
	 */
	public static ApiResult error(String message) {
		return result(ApiCode.INTERNAL_SERVER_ERROR, message, null);
	}

	/**
	 * 返回枚举类ApiCode中状态码和状态描述。
	 *
	 * @param apiCode 枚举类ApiCode
	 * @return 失败
	 */
	public static ApiResult error(ApiCode apiCode) {
		return result(apiCode, null);
	}

	/**
	 * 返回HttpStatus类中的状态码和状态描述。
	 *
	 * @param httpStatus spring-web:版本号.jar中的org.springframework.http包下的HttpStatus类
	 * @return 失败
	 */
	public static ApiResult error(HttpStatus httpStatus) {
		return result(httpStatus.value(), httpStatus.getReasonPhrase());
	}

	/**
	 * 返回枚举类ApiCode中状态码，以及传入的状态描述。
	 *
	 * @param apiCode 枚举类ApiCode
	 * @param message 状态描述
	 * @return 失败
	 */
	public static ApiResult error(ApiCode apiCode, String message) {
		return result(apiCode, message, null);
	}

	/**
	 * 传入参数code和message的值，返回对应的响应结果。
	 *
	 * @param code    状态码
	 * @param message 状态描述
	 * @return 失败
	 */
	public static ApiResult error(int code, String message) {
		return result(code, message);
	}

	/**
	 * <p>apache的commons-xxx.jar的系列产品（比如：commons-lang3.jar）是根据jdk1.8的技术来写的
	 * <p>StringUtils.isBlank(null)      = true
	 * <p>StringUtils.isBlank("")        = true
	 * <p>StringUtils.isBlank(" ")       = true
	 * <p>StringUtils.isBlank("bob")     = false
	 * <p>StringUtils.isBlank("  bob  ") = false
	 */
	private static boolean isBlank(CharSequence cs) {
		int strLen;
		if (cs != null && (strLen = cs.length()) != 0) {
			for (int i = 0; i < strLen; ++i) {
				if (!Character.isWhitespace(cs.charAt(i))) {
					return false;
				}
			}
			return true;
		} else {
			return true;
		}
	}

}
